/**    
* @Title: AppInstance.java  
* @Package com.kaver.spring   
* @author roc   
* @date 2019年1月31日 上午10:05:35  
* @version V1.0  
* @copyright kaver 
*/
package com.kaver.spring;

import java.io.File;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertiesPropertySource;

import com.kaver.constant.PropertyConstant;
import com.kaver.exception.ConfException;

/**
 * @ClassName: AppInstance
 * @Description: 客户端信息
 * @author roc
 * @date 2019年1月31日 上午10:05:35
 * 
 */
public class AppInstance {

	private final static Logger logger = LoggerFactory.getLogger(AppInstance.class);

	private static String appName;

	private static String env;

	private static Long version;

	private static String cachePath;

	private static String serverUrl;

	public static String getAppName() {
		return appName;
	}

	public static String getEnv() {
		return env;
	}

	public static Long getVersion() {
		return version;
	}

	public static void setVersion(Long version) {
		AppInstance.version = version;
	}

	public static String getCachePath() {
		return cachePath;
	}

	public static String getServerUrl() {
		return serverUrl;
	}

	public static void init(String appName, String env, String cachePath, String serverUrl) {
		AppInstance.appName = appName;
		AppInstance.env = env;
		AppInstance.cachePath = cachePath;
		AppInstance.serverUrl = serverUrl;
	}

	public static void initAppInstance(ConfigurableEnvironment environment) {
		String appName = getProperty(PropertyConstant.APPNAME, environment);
		String env = getProperty(PropertyConstant.ENV, environment);
		System.out.println("配置中心选择环境:" + env);
		String cachePath = getProperty(PropertyConstant.CACHE_PATH, environment);
		String serverUrl = getProperty(PropertyConstant.SERVER_URL, environment);
		AppInstance.init(appName, env, cachePath, serverUrl);
	}

	public static void initAppInstance(Properties environment) {
		String appName = getProperty(PropertyConstant.APPNAME, environment);
		String env = getProperty(PropertyConstant.ENV, environment);
		System.out.println("配置中心选择环境:" + env);
		String cachePath = getProperty(PropertyConstant.CACHE_PATH, environment);
		String serverUrl = getProperty(PropertyConstant.SERVER_URL, environment);
		AppInstance.init(appName, env, cachePath, serverUrl);
	}

	private static String getProperty(String key, ConfigurableEnvironment environment) {
		// 优先级 虚拟机参数 > spring environment > default
		if (System.getProperty(key) != null) {
			return System.getProperty(key);
		} else if (environment.containsProperty(key)) {
			return environment.getProperty(key);
		} else {
			String profile = getSpringProfilesActive(environment);
			if (PropertyConstant.APPNAME.equals(key)) {
				String springApplicatioName = environment.getProperty(PropertyConstant.SPRING_APPLICATION_NAME);
				if (springApplicatioName == null) {
					throw new ConfException("配置中心项目名称未配置，" + PropertyConstant.APPNAME + "和"
							+ PropertyConstant.SPRING_APPLICATION_NAME + "至少配置一个");
				}
				return springApplicatioName;
			} else if (PropertyConstant.ENV.equals(key)) {
				return profile;
			} else if (PropertyConstant.CACHE_PATH.equals(key)) {
				return System.getProperty("user.dir") + File.separator + "conf/";
			} else if (PropertyConstant.SERVER_URL.equals(key)) {
				if (PropertyConstant.CONF_PROD_ENV.equals(profile) || PropertyConstant.CONF_PROD_PRE.equals(profile)) {
					return PropertyConstant.CONF_PROD_SERVER_URL;
				} else {
					return PropertyConstant.CONF_STAGE_SERVER_URL;
				}
			} else {
				return null;
			}
		}
	}

	private static String getProperty(String key, Properties environment) {
		// 优先级 虚拟机参数 > spring environment > default
		if (System.getProperty(key) != null) {
			return System.getProperty(key);
		} else if (environment.containsKey(key)) {
			return environment.getProperty(key);
		} else {
			String profile = getSpringProfilesActive(environment);
			if (PropertyConstant.APPNAME.equals(key)) {
				String springApplicatioName = environment.getProperty(PropertyConstant.SPRING_APPLICATION_NAME);
				if (springApplicatioName == null) {
					throw new ConfException("配置中心项目名称未配置，" + PropertyConstant.APPNAME + "和"
							+ PropertyConstant.SPRING_APPLICATION_NAME + "至少配置一个");
				}
				return springApplicatioName;
			} else if (PropertyConstant.ENV.equals(key)) {
				return profile;
			} else if (PropertyConstant.CACHE_PATH.equals(key)) {
				return System.getProperty("user.dir") + File.separator + "conf/";
			} else if (PropertyConstant.SERVER_URL.equals(key)) {
				if (PropertyConstant.CONF_PROD_ENV.equals(profile) || PropertyConstant.CONF_PROD_PRE.equals(profile)) {
					return PropertyConstant.CONF_PROD_SERVER_URL;
				} else {
					return PropertyConstant.CONF_STAGE_SERVER_URL;
				}
			} else {
				return null;
			}
		}
	}

	// 获取一个profile
	private static String getSpringProfilesActive(ConfigurableEnvironment environment) {
		String springProfilesActive = environment.getProperty(PropertyConstant.SPRING_PROFILES_ACTIVE);
		if (springProfilesActive == null) {
			throw new ConfException("配置中心项目环境未配置，" + PropertyConstant.ENV + "和"
					+ PropertyConstant.SPRING_PROFILES_ACTIVE + "至少配置一个");
		}
		String profile = null;
		String[] profiles = springProfilesActive.split(",");// 如果配置多个取最后一个
		for (int i = profiles.length -1; i >=0;i--) {
		    if (PropertyConstant.DEFAULT_ENVS.contains(profiles[i])) {
		        profile = profiles[i];
		    }
		}
		if (profile == null) {
		    profile = profiles[profiles.length - 1];
		}
		return profile;
	}

	// 获取一个profile
	private static String getSpringProfilesActive(Properties environment) {
		String springProfilesActive = environment.getProperty(PropertyConstant.SPRING_PROFILES_ACTIVE);
		if (springProfilesActive == null) {
			throw new ConfException("配置中心项目环境未配置，" + PropertyConstant.ENV + "和"
					+ PropertyConstant.SPRING_PROFILES_ACTIVE + "至少配置一个");
		}
		String[] profiles = springProfilesActive.split(",");// 如果配置多个取最后一个
		for (int i = profiles.length -1; i >=0;i--) {
            if (PropertyConstant.DEFAULT_ENVS.contains(profiles[i])) {
                return profiles[i];
            }
        }
		return profiles[profiles.length - 1];
	}

	public static void loadLocalAndRomoteProperties() {
		try {
			RomoteRepository.getInstance().load();
			LocalCacheRepository.getInstance().load();
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("loadLocalAndRomoteProperties error", e);
		}
	}

	public static void merge(ConfigurableEnvironment environment) {
		try {
			if (RomoteRepository.isEnable()) {
				LocalCacheRepository.getInstance().resetMe(RomoteRepository.getInstance().getProperties());
				LocalCacheRepository.getInstance().restore();
			}
			Properties properties = LocalCacheRepository.getInstance().getProperties();
			PropertiesPropertySource propertySource = new PropertiesPropertySource("local", properties);
			environment.getPropertySources().addFirst(propertySource);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("merge properties error", e);
		}

	}

	public static void merge(Properties properties) {
		try {
			if (RomoteRepository.isEnable()) {
				RomoteRepository.getInstance().merge(properties);
				LocalCacheRepository.getInstance().resetMe(RomoteRepository.getInstance().getProperties());
				LocalCacheRepository.getInstance().restore();
			} else {
				LocalCacheRepository.getInstance().merge(properties);
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("merge properties error", e);
		}
	}
}
